#include "ui/ffcapwindow.h"
#include <QApplication>

#include"opengl/ffglrenderwidget.h"
#include"demuxer/ffdemuxer.h"
#include"queue/ffapacketqueue.h"
#include"queue/ffvpacketqueue.h"
#include"queue/ffvframequeue.h"
#include"queue/ffaframequeue.h"

#include"render/ffvrender.h"
#include"thread/ffvdecoderthread.h"
#include"thread/ffdemuxerthread.h"
#include"thread/ffadecoderthread.h"
#include"decoder/ffadecoder.h"

#include"muxer/ffmuxer.h"
#include"thread/ffamuxerthread.h"
#include"thread/ffvmuxerthread.h"
#include"thread/ffmuxerthread.h"
#include"encoder/ffaencoder.h"
#include"encoder/ffvencoder.h"
#include"thread/ffaencoderthread.h"
#include"thread/ffvencoderthread.h"

static FFGLRenderWidget* renderWidget = nullptr;
static FFDemuxer* vDemuxer = nullptr;
static FFAPacketQueue* aPktQueue = nullptr;
static FFVPacketQueue* vPktQueue = nullptr;
static FFDemuxerThread* vDemuxerThread = nullptr;
static FFVRender* vRender = nullptr;
static FFVDecoder* vDecoder = nullptr;
static FFVDecoderThread* vDecoderThread = nullptr;
static FFVFrameQueue* vFrmQueue = nullptr;

static FFADecoder* aDecoder = nullptr;
static FFADecoderThread* aDecoderThread = nullptr;
static FFDemuxer* aDemuxer = nullptr;
static FFDemuxerThread* aDemuxerThread = nullptr;


static FFAFrameQueue* aEncoderFrmQueue = nullptr;
static FFVFrameQueue* vEncoderFrmQueue = nullptr;

static FFAPacketQueue* aEncoderPktQueue = nullptr;
static FFVPacketQueue* vEncoderPktQueue = nullptr;

static FFMuxer* muxer = nullptr;
//static FFAMuxerThread* aMuxerThread = nullptr;
//static FFVMuxerThread* vMuxerThread = nullptr;
static FFAEncoder* aEncoder = nullptr;
static FFVEncoder* vEncoder = nullptr;
static FFAEncoderThread* aEncoderThread = nullptr;
static FFVEncoderThread* vEncoderThread = nullptr;

static FFMuxerThread* muxerThread = nullptr;

void registerType(){
    qRegisterMetaType<uint8_t*>("uint8_t*");
}

void util(){
    registerType();

    aPktQueue = new FFAPacketQueue();
    vPktQueue = new FFVPacketQueue();
    vFrmQueue = new FFVFrameQueue();

    aEncoderFrmQueue = new FFAFrameQueue();
    vEncoderFrmQueue = new FFVFrameQueue();
    aEncoderPktQueue = new FFAPacketQueue();
    vEncoderPktQueue = new FFVPacketQueue();

    vDemuxer = new FFDemuxer();
    vDemuxerThread = new FFDemuxerThread();
    vDemuxerThread->init(vDemuxer);

    vRender = new FFVRender();
    vDecoder = new FFVDecoder();
    vDecoderThread = new FFVDecoderThread();

    renderWidget = new FFGLRenderWidget();

    aDecoder = new FFADecoder();
    aDecoderThread = new FFADecoderThread();
    aDemuxer = new FFDemuxer();
    aDemuxerThread = new FFDemuxerThread();

    aDemuxer->init("audio=麦克风阵列 (Realtek(R) Audio)","dshow",aPktQueue,nullptr);
    aDemuxerThread->init(aDemuxer);
    aDecoder->init(aDemuxer->getAStream(),aEncoderFrmQueue); //编码帧队列
    aDecoderThread->init(aDecoder,aPktQueue);

    vDemuxer->init("video=Integrated Camera","dshow",nullptr,vPktQueue);
    vDecoder->init(vDemuxer->getVStream(),vFrmQueue,vEncoderFrmQueue); //编码队列+解码队列
    vDecoderThread->init(vDecoder,vPktQueue);

    vRender->init(vDecoder,vFrmQueue,renderWidget);


   //编码初始化
    aEncoder = new FFAEncoder();
    aEncoder->init(aEncoderPktQueue);

    vEncoder = new FFVEncoder();
    vEncoder->init(vEncoderPktQueue);

    muxer = new FFMuxer();
    muxer->init("capture.mp4");

//    aMuxerThread = new FFAMuxerThread();
//    aMuxerThread->init(aEncoderPktQueue,muxer,aEncoder);

//    vMuxerThread = new FFVMuxerThread();
//    vMuxerThread->init(vEncoderPktQueue,muxer);

    muxerThread = new FFMuxerThread();
    muxerThread->init(aEncoderPktQueue,vEncoderPktQueue,muxer,aEncoder,vEncoder);

    aEncoderThread = new FFAEncoderThread();
    aEncoderThread->init(aEncoder,muxer,aDecoder,aEncoderFrmQueue);

    vEncoderThread = new FFVEncoderThread();
    vEncoderThread->init(vEncoder,muxer,vDecoder,vEncoderFrmQueue);
}

void start(){
    renderWidget->show();

    aDemuxerThread->start();
    aDecoderThread->start();

    vDemuxerThread->start();
    vDecoderThread->start();
    vRender->start();

    aEncoderThread->start();
    vEncoderThread->start();

//    aMuxerThread->start();
//    vMuxerThread->start();
    muxerThread->start();
}
void Test(){
    util();
    start();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    FFCapWindow w;
//    w.show();

    Test();
    return a.exec();
}
